package com.lin.java.tool.oss.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import com.lin.java.tool.common.ex.BizException;
import com.lin.java.tool.general.dao.mapper.SysFileMapper;
import com.lin.java.tool.general.dao.po.SysFileEntity;
import com.lin.java.tool.oss.model.UploadFileData;
import com.lin.java.tool.oss.model.dto.DownloadRespDTO;
import com.lin.java.tool.oss.model.dto.UploadRespDTO;
import com.lin.java.tool.oss.service.OssService;
import com.lin.java.tool.oss.storage.StorageEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author linjiang
 * @date 2024/7/29
 * @fn 只支持yaml配置的文件服务，如果业务要求数据库支持配置，请关闭配置。
 */
@Service
public class OssServiceImpl implements OssService {
    @Value("${file.storage.platform:''}")
    public String platform;
    @Autowired(required = false)
    StorageEngine storageEngine;
    @Autowired
    SysFileMapper fileRecordMapper;

    @Override
    public SysFileEntity upload(MultipartFile file) throws Exception {
        check();
        String originalFilename = file.getOriginalFilename();

        // 构建新文件名称
        String suffix = FileUtil.getSuffix(originalFilename);
        String newFilename = UUID.fastUUID().toString(true) + "." + suffix;
        // 会按照当天的时间戳进行来管理文件
        String path = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";
        String objectName = path.concat(newFilename);
        // 上传文件
        UploadRespDTO respDTO = storageEngine.put(UploadFileData.builder()
                .objectName(objectName)
                .fileStream(file.getInputStream())
                .build()
        );

        SysFileEntity sysFileRecordEntity = new SysFileEntity();
        sysFileRecordEntity.setBucket(respDTO.getBucket());
        sysFileRecordEntity.setPath(objectName);
        sysFileRecordEntity.setOriginFileName(originalFilename);
        sysFileRecordEntity.setSize(file.getSize());
        sysFileRecordEntity.setSuffix(suffix);
        sysFileRecordEntity.setPlatform(platform);
        sysFileRecordEntity.setSomeObj(UUID.fastUUID().toString(true));
        fileRecordMapper.insert(sysFileRecordEntity);
        return sysFileRecordEntity;
    }

    @Override
    public void download(Long fileId, HttpServletResponse response) throws IOException {
        check();
        SysFileEntity record = fileRecordMapper.selectById(fileId);
        if (record == null) {
            throw new BizException("文件不存在！");
        }
        DownloadRespDTO downloadFileData = storageEngine.get(record.getPath());
        write(record, response, downloadFileData);
    }

    private void write(SysFileEntity record, HttpServletResponse response, DownloadRespDTO downloadFileData) throws IOException {
        response.reset();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(record.getOriginFileName(), Charset.defaultCharset()));
        IoUtil.write(response.getOutputStream(), true, downloadFileData.getBytes());
    }

    private void check() {
        if (storageEngine == null) {
            throw new BizException("请先配置文件存储引擎！");
        }
    }
}
